use std::any::Any;
use std::fmt::Debug;
use std::sync::Arc;
use async_trait::async_trait;
use tracing::{trace, debug, info, warn, error};
use crate::actor::{ActorError, PID, SystemMessage, DefaultActorContext, ActorContext};

/// Message type that is Send + Sync
pub type SyncMessage = Box<dyn Any + Send + Sync>;

/// Convert a regular message to a SyncMessage
/// This function should be used to convert normal messages to thread-safe messages
/// that can be safely passed between actors and middleware components
pub fn to_sync_message<T: Any + Send + Sync + 'static>(message: T) -> SyncMessage {
    Box::new(message)
}

/// Sender interface for sending messages
#[async_trait]
pub trait Sender: Send + Sync {
    /// Send a user message to the target PID
    async fn send(&self, target: PID, message: SyncMessage) -> Result<(), ActorError>;
    
    /// Send a system message to the target PID
    async fn send_system(&self, target: PID, message: SystemMessage) -> Result<(), ActorError>;
}

/// Receiver interface for receiving messages
#[async_trait]
pub trait Receiver: Send + Sync {
    /// Receive a user message
    async fn receive(&self, context: &mut DefaultActorContext, message: SyncMessage) -> Result<(), ActorError>;
    
    /// Receive a system message
    async fn receive_system(&self, context: &mut DefaultActorContext, message: SystemMessage) -> Result<(), ActorError>;
}

/// Sender middleware interface for intercepting outbound messages
#[async_trait]
pub trait SenderMiddleware: Send + Sync {
    /// Process outbound user messages
    async fn send(&self, next: Arc<dyn Sender>, target: PID, message: SyncMessage) -> Result<(), ActorError>;
    
    /// Process outbound system messages
    async fn send_system(&self, next: Arc<dyn Sender>, target: PID, message: SystemMessage) -> Result<(), ActorError>;
}

/// Receiver middleware interface for intercepting inbound messages
#[async_trait]
pub trait ReceiverMiddleware: Send + Sync {
    /// Process inbound user messages
    async fn receive(&self, next: Arc<dyn Receiver>, context: &mut DefaultActorContext, message: SyncMessage) -> Result<(), ActorError>;
    
    /// Process inbound system messages
    async fn receive_system(&self, next: Arc<dyn Receiver>, context: &mut DefaultActorContext, message: SystemMessage) -> Result<(), ActorError>;
}

/// Wrapper for sender middleware
#[derive(Clone)]
pub struct SenderMiddlewareWrapper {
    middleware: Arc<dyn SenderMiddleware>,
    next: Arc<dyn Sender>,
}

impl SenderMiddlewareWrapper {
    /// Create a new sender middleware wrapper
    pub fn new(middleware: Arc<dyn SenderMiddleware>, next: Arc<dyn Sender>) -> Self {
        Self { middleware, next }
    }
}

#[async_trait]
impl Sender for SenderMiddlewareWrapper {
    async fn send(&self, target: PID, message: SyncMessage) -> Result<(), ActorError> {
        self.middleware.send(self.next.clone(), target, message).await
    }
    
    async fn send_system(&self, target: PID, message: SystemMessage) -> Result<(), ActorError> {
        self.middleware.send_system(self.next.clone(), target, message).await
    }
}

/// Wrapper for receiver middleware
#[derive(Clone)]
pub struct ReceiverMiddlewareWrapper {
    middleware: Arc<dyn ReceiverMiddleware>,
    next: Arc<dyn Receiver>,
}

impl ReceiverMiddlewareWrapper {
    /// Create a new receiver middleware wrapper
    pub fn new(middleware: Arc<dyn ReceiverMiddleware>, next: Arc<dyn Receiver>) -> Self {
        Self { middleware, next }
    }
}

#[async_trait]
impl Receiver for ReceiverMiddlewareWrapper {
    async fn receive(&self, context: &mut DefaultActorContext, message: SyncMessage) -> Result<(), ActorError> {
        self.middleware.receive(self.next.clone(), context, message).await
    }
    
    async fn receive_system(&self, context: &mut DefaultActorContext, message: SystemMessage) -> Result<(), ActorError> {
        self.middleware.receive_system(self.next.clone(), context, message).await
    }
}

/// Logging middleware implementation for demonstration
#[derive(Debug, Clone)]
pub struct LoggingMiddleware {
    prefix: String,
}

impl LoggingMiddleware {
    /// Create a new logging middleware with the given prefix
    pub fn new(prefix: impl Into<String>) -> Self {
        Self {
            prefix: prefix.into(),
        }
    }
}

#[async_trait]
impl SenderMiddleware for LoggingMiddleware {
    async fn send(&self, next: Arc<dyn Sender>, target: PID, message: SyncMessage) -> Result<(), ActorError> {
        debug!("{} Sending message to {}", self.prefix, target);
        next.send(target, message).await
    }
    
    async fn send_system(&self, next: Arc<dyn Sender>, target: PID, message: SystemMessage) -> Result<(), ActorError> {
        debug!("{} Sending system message to {}", self.prefix, target);
        next.send_system(target, message).await
    }
}

#[async_trait]
impl ReceiverMiddleware for LoggingMiddleware {
    async fn receive(&self, next: Arc<dyn Receiver>, context: &mut DefaultActorContext, message: SyncMessage) -> Result<(), ActorError> {
        debug!("{} Receiving message for {}", self.prefix, context.self_pid());
        next.receive(context, message).await
    }
    
    async fn receive_system(&self, next: Arc<dyn Receiver>, context: &mut DefaultActorContext, message: SystemMessage) -> Result<(), ActorError> {
        debug!("{} Receiving system message for {}", self.prefix, context.self_pid());
        next.receive_system(context, message).await
    }
} 